package com.foreveross.bsl.common.utils.web;

import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.Maps;

/**
 * 一个简单的自定义条件过虑类，包括字段、操作符和值。 操作符目前包括EQ, LIKE, GT, LT, GTE,
 * LTE,分别表示：等于，like，大于，小于，大于等于，小于等于
 * 
 * @author Wangyi
 * @version v1.0
 * 
 * @date 2013-9-11
 * 
 */
public class QueryFilter {

	public static final QueryFilter EMPTY_FILTER = new QueryFilter();

	public enum Operator {
		EQ, LIKE, GT, LT, GTE, LTE
	}

	@JsonProperty("name")
	private final String fieldName;

	@JsonProperty("value")
	private final Object value;

	@JsonProperty("op")
	private final Operator operator;

	private QueryFilter() {
		this.fieldName = null;
		this.value = null;
		this.operator = null;
	}

	@JsonCreator
	public QueryFilter(@JsonProperty("name") String fieldName, @JsonProperty("op") Operator operator,
			@JsonProperty("value") Object value) {
		this.fieldName = fieldName;
		this.value = value;
		this.operator = operator;
	}

	public static final QueryFilter eq(String fieldName, Object value) {
		return new QueryFilter(fieldName, Operator.EQ, value);
	}

	public static final QueryFilter like(String fieldName, Object value) {
		return new QueryFilter(fieldName, Operator.LIKE, value);
	}

	public static final QueryFilter gt(String fieldName, Object value) {
		return new QueryFilter(fieldName, Operator.GT, value);
	}

	public static final QueryFilter lt(String fieldName, Object value) {
		return new QueryFilter(fieldName, Operator.LT, value);
	}

	public static final QueryFilter gte(String fieldName, Object value) {
		return new QueryFilter(fieldName, Operator.GTE, value);
	}

	public static final QueryFilter lte(String fieldName, Object value) {
		return new QueryFilter(fieldName, Operator.LTE, value);
	}

	@JsonIgnore
	public String getFilterExpression() {
		if (QueryFilter.EMPTY_FILTER.equals(this)) {
			return null;
		}
		StringBuilder sb = new StringBuilder();
		sb.append(this.getFilterExpressionHead()).append('=').append(this.value);
		return sb.toString();
	}

	@JsonIgnore
	public String getFilterExpressionHead() {
		if (QueryFilter.EMPTY_FILTER.equals(this)) {
			return null;
		}
		StringBuilder sb = new StringBuilder();
		sb.append(this.operator).append('_').append(this.fieldName);
		return sb.toString();
	}

	/**
	 * searchParams中的key为特殊约定的过虑格式：OPERATOR_FIELDNAME, eg: EQ_name，表示name等于;
	 * searchParams中的value则是条件的具体值
	 * 
	 * @param searchParams
	 * @return
	 */
	public static Map<String, QueryFilter> parseToFilterMap(Map<String, Object> searchParams) {
		Map<String, QueryFilter> filters = Maps.newHashMap();

		for (Entry<String, Object> entry : searchParams.entrySet()) {
			// 过滤掉空值
			String key = entry.getKey();
			Object value = entry.getValue();
			if (value instanceof String) {
				String strValue = (String) value;
				if (StringUtils.isBlank(strValue)) {
					continue;
				}
				value = strValue.trim();
			}

			int i = key.indexOf("_");
			if (i <= 0 || i == key.length() - 1) {
				// ignored
				// continue;
				throw new IllegalArgumentException(key + " is not a valid query filter name");
			}
			// 拆分operator与filedAttribute
			String filedName = key.substring(i + 1);
			Operator operator = Operator.valueOf(key.substring(0, i));

			// 创建searchFilter
			QueryFilter filter = new QueryFilter(filedName, operator, value);
			filters.put(key, filter);
		}

		return filters;
	}

	/**
	 * searchParams中的key为特殊约定的过虑格式：OPERATOR_FIELDNAME, eg: EQ_name，表示name等于;
	 * searchParams中的value则是条件的具体值
	 * 
	 * @param searchParams
	 * @return
	 */
	public static Collection<QueryFilter> parseToFilters(Map<String, Object> searchParams) {
		return parseToFilterMap(searchParams).values();
	}

	/**
	 * @return the fieldName
	 */
	public String getFieldName() {
		return fieldName;
	}

	/**
	 * @return the value
	 */
	public Object getValue() {
		return value;
	}

	/**
	 * @return the operator
	 */
	public Operator getOperator() {
		return operator;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		return HashCodeBuilder.reflectionHashCode(this);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		return EqualsBuilder.reflectionEquals(this, obj);
	}
}
